package form.ui
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	
	import form.ui.core.Border;
	import form.ui.core.FMSprite;
	
	
	public class BorderImage extends FMSprite
	{
		public static const ERROR_RETRY_TIMES:uint = 3;
		
		public var border:Border;		
		public var borderAlpha:Number = 1;
		public var context:LoaderContext;
		
		private var contentMask:Sprite;
		private var loader:Loader;
		private var streamLoader:URLStream;
		private var lastLoaded:String;
		private var errorRetryCount:int = 0
		
		public function BorderImage()
		{
			super();
			
			this.minWidth = 80;
			this.minHeight = 80;
			
			contentMask = new Sprite();			
			addChild(contentMask);
			this.mask = contentMask;
			
			createLoader();
			
			this.border = new Border();			
			addChild(this.border);
			
			this.registerStyle("borderColor");
			this.registerStyle("borderWidth");
			this.registerStyle("opacity"); 
		}
		
		private function createLoader():void
		{
			if(loader && contains(loader))
			{
				loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
				removeChild(loader);
			}
			loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
			addChildAt(loader, 0);
		}
		
		private function createStreamLoader():void
		{
			streamLoader = new URLStream();
			streamLoader.addEventListener(Event.COMPLETE, onStreamLoad);
			streamLoader.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
			streamLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoadError);
		}
		
		private function onStreamLoad(e:Event):void
		{
			if(!loader) createLoader();
			var bytes:ByteArray = new ByteArray();
			streamLoader.readBytes(bytes, 0, streamLoader.bytesAvailable);
			streamLoader.close();
			loader.unload();
			loader.loadBytes(bytes, this.context);
		}
		
		private function updateMask():void
		{
			var w:Number = this.width > 0 ? this.width : this.minWidth;
			var h:Number = this.height > 0 ? this.height : this.minHeight;
			contentMask.graphics.clear();
			contentMask.graphics.beginFill(0);
			contentMask.graphics.drawRect(0,0,w, h);
			contentMask.graphics.endFill();
		}
		
		private function onLoaded(e:Event):void
		{
			lastLoaded = e.target.url;
			resize();
		}
		
		protected function resize():void
		{
			if(loader.width <= 0 || loader.height <= 0) return;
			if(loader.scaleX != 1 || loader.scaleY != 1) loader.scaleX = loader.scaleY = 1;				
			
			var sw:Number = this.width;
			var sh:Number = this.height;
			
			if(loader.width > sw && loader.height > sh)
			{
				if(loader.width > loader.height)
				{
					loader.width = sw;	
					loader.scaleY = loader.scaleX;				
				}
				else
				{
					loader.height = sh;
					loader.scaleX = loader.scaleY;
				}
				
			}
			
			if(loader.width < sw)
			{
				loader.width = sw;
				loader.scaleY = loader.scaleX;
			}
			
		}
		
		private var _useStream:Boolean = false;
		public function get useStream():Boolean
		{
			return _useStream;
		}
		public function set useStream(value:Boolean):void
		{
			if(_useStream != value)
			{
				_useStream = value;
			}
		}
		
		private var _source:String;
		public function set source(value:String):void
		{			
			if(_source != value)
			{
				this._source = value;
				this.loader.unload();
				
				if(useStream)
				{
					if(!streamLoader)createStreamLoader();
					streamLoader.load(new URLRequest(this.source));
				}	
				else
				{
					this.loader.load(new URLRequest(this.source), context);
				}	
			}
		}
		public function get source():String
		{
			return this._source;
		}
		
		private var _borderColor:uint = 0xFFFFFF;
		public function set borderColor(value:uint):void
		{
			_borderColor = value;
		}
		public function get borderColor():uint
		{
			return _borderColor;
		}
		
		private var _borderWidth:uint = 1;
		public function get borderWidth():uint
		{
			return _borderWidth;
		}
		public function set borderWidth(value:uint):void
		{
			_borderWidth = value;
		}
		
		public function set opacity(value:Number):void
		{
			this.borderAlpha = value;
		}
		
		public function unload():void
		{
			this.loader.unload();
		}
		
		override public function draw():void
		{   
            super.draw()
            if(!this.width || !this.height) return;
            updateMask();
            border.borderAlpha = this.borderAlpha;
			border.borderColor = this.borderColor;
			border.borderWidth = this.borderWidth;
			border.width = this.width;
			border.height = this.height;
        }   
        
        override public function updateStyle():void
        {
        	super.updateStyle();
        	this.draw();
        }
        
        private function onLoadError(e:Event):void
		{
			trace(e.target + " " + e);
			if(e.target == streamLoader && errorRetryCount <= ERROR_RETRY_TIMES)
			{
				errorRetryCount++;
				streamLoader.load(new URLRequest(this.source));
			}
		}

	}
}